//
//  SSWBNetworkManager.swift
//  shanshanlol微博
//
//  Created by 叶竞泽 on 2017/1/16.
//  Copyright © 2017年 JingZe. All rights reserved.
//

import UIKit
import AFNetworking

enum WBHTTPMethod {
    case GET
    case POST
}

/// 网络管理工具
class SSWBNetworkManager: AFHTTPSessionManager {
    
    /// 单例 / 常量
    static let shared: SSWBNetworkManager = {
        let instance = SSWBNetworkManager()
        
        // 设置支持的数据类型
        instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
        return instance
    }()
    
    /// 用户账户的懒加载属性
    lazy var userAccount = SSWBUserAccount()
    
    /// 用户登录标记
    var userLogon: Bool {
        return userAccount.access_token != nil
    }
    
    /// 专门负责拼接token网络请求方法
    ///
    /// - Parameters:
    ///   - method: GET / POST
    ///   - urlString: 请求的URL
    ///   - parameters: URL参数
    ///   - name: 服务器接收的字段名,默认为nil,如果为nil,就不是上传文件
    ///   - data: 文件二进制数据
    ///   - completion: 回调方法
    func tokenRequest(method: WBHTTPMethod = .GET, urlString: String, parameters: [String: Any]?, name:String? = nil, data: Data? = nil, completion: @escaping (_ json: Any?, _ isSuccess: Bool) -> ()) {
        
        // 1.处理token
        // 判断token是否为nil,如果为nil就直接返回,程序执行过程中,token一般不会为nil
        guard let token = userAccount.access_token else {
            
            
            print("没有Token,需要登录")
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserShouldLoginNotification), object: nil, userInfo: nil)
            
            completion(nil, false)
            return
        }
        
        // 2.判断参数字典是否存在,如果为nil,应该新建一个字典
        var parametersNew = parameters
        if parametersNew == nil {
            parametersNew = [String: Any]()
        }
        
        // 3.设置参数字典
        parametersNew!["access_token"] = token
        
        // 4.判断是否是上传文件
        if let name = name, let data = data {
            // 是上传文件
            upload(urlString: urlString, params: parametersNew, name: name, picData: data, completion: completion)
        } else {
            // 不是上传文件,调用request发起请求
            request(method: method, urlString: urlString, parameters: parametersNew, completion: completion)
        }
    }
    
    /// 上传文件 - 封装AFN的上传文件方法
    /// 上传文件必须是POST方法, GET只能获取数据
    ///
    /// - Parameters:
    ///   - urlString: URL
    ///   - params: 参数
    ///   - name: 接受上传数据的服务器字段(要咨询公司后台) pic
    ///   - data: 图片二进制数据
    ///   - completion: 回调方法
    func upload(urlString: String, params: [String: Any]?, name: String, picData: Data, completion: @escaping (_ json: Any?, _ isSuccess: Bool) -> ()) {
        
        let url = urlString
        
        post(url, parameters: params, constructingBodyWith: { (multipartFormData) in
            
            // FIXME: - 创建formData
            /**
             withFileData - 要上传的二进制数据
             name - 服务器接收的字段名
             fileName - 保存在服务器的文件名(现在大部分服务器可以随便写,很多服务器,上传完成后,会生成大图,中图,缩略图...)
             mimeType - 告诉服务器上传文件的类型(image/png, image/jpg, image/gif),也可以使用application/octet-stream
             */
            multipartFormData.appendPart(withFileData: picData, name: name, fileName: "xxx", mimeType: "application/octet-stream")
            
        }, progress: { (progress) in
            
        }, success: { (_, json) in
            
            completion(json, true)
            
        }) { (dataTask, error) in
            
            // 针对403处理token过期
            // 没有新浪审核完成的应用,每天刷新的次数有限
            // 超出后会被锁定,一直是403
            // 解决办法,新建应用程序
            if (dataTask?.response as? HTTPURLResponse)?.statusCode == 403 {
                
                print("Token过期了")
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserShouldLoginNotification), object: "bad token", userInfo: nil)
            }
            
            print("网络请求错误\(error)")
            completion(nil, false)
            
        }
        
    }
    
    /// 使用一个函数封装POST和GET请求
    ///
    /// - Parameters:
    ///   - method: WBHTTPMethod类型
    ///   - urlString: url地址
    ///   - parameters: url请求参数,字典类型
    ///   - completion: 回调
    func request(method: WBHTTPMethod = .GET, urlString: String, parameters: [String: Any]?, completion: @escaping (_ json: Any?, _ isSuccess: Bool) -> ()) {
        
        /// 成功回调
        let success = { (task: URLSessionDataTask, json: Any) in
            
            completion(json, true)
        }
        
        /// 失败回调
        let failure = { (task: URLSessionDataTask?, error: Error) in
            
            // 针对403处理token过期
            // 没有新浪审核完成的应用,每天刷新的次数有限
            // 超出后会被锁定,一直是403
            // 解决办法,新建应用程序
            if (task?.response as? HTTPURLResponse)?.statusCode == 403 {
                
                print("Token过期了")
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserShouldLoginNotification), object: "bad token", userInfo: nil)
            }
            // error内容通常比较多
            print("网络请求错误\(error)")
            completion(nil, false)
        }
        
        if method == .GET {
            
            get(urlString, parameters: parameters, progress: nil, success: success, failure: failure)
            
        } else {
            
            post(urlString, parameters: parameters, progress: nil, success: success, failure: failure)
            
        }
        
    }
}
